#!/usr/bin/env node

/**
 * Minecraft面板备份脚本
 * 用于备份数据库和配置文件
 */

const fs = require('fs');
const path = require('path');
const archiver = require('archiver');
const moment = require('moment');

console.log('==========================================');
console.log('  Minecraft面板备份脚本');
console.log('==========================================');
console.log();

// 配置
const config = {
    backupDir: path.join(__dirname, '..', 'backups'),
    databasePath: path.join(__dirname, '..', 'database.sqlite'),
    envPath: path.join(__dirname, '..', '.env'),
    configDir: path.join(__dirname, '..', 'config'),
    uploadsDir: path.join(__dirname, '..', 'public', 'uploads'),
    maxBackups: 30 // 保留最近30个备份
};

// 创建备份目录
function createBackupDirectory() {
    if (!fs.existsSync(config.backupDir)) {
        fs.mkdirSync(config.backupDir, { recursive: true });
        console.log('✅ 创建备份目录');
    }
}

// 生成备份文件名
function generateBackupName() {
    const timestamp = moment().format('YYYYMMDD_HHmmss');
    return `minecraft-panel-backup-${timestamp}`;
}

// 备份数据库
function backupDatabase(backupName) {
    const backupPath = path.join(config.backupDir, `${backupName}.sqlite`);
    
    if (fs.existsSync(config.databasePath)) {
        fs.copyFileSync(config.databasePath, backupPath);
        console.log(`✅ 数据库备份完成: ${backupName}.sqlite`);
        return backupPath;
    } else {
        console.log('⚠️  数据库文件不存在，跳过数据库备份');
        return null;
    }
}

// 备份配置文件
function backupConfig(backupName) {
    const backupPath = path.join(config.backupDir, `${backupName}.zip`);
    const output = fs.createWriteStream(backupPath);
    const archive = archiver('zip', { zlib: { level: 9 } });

    return new Promise((resolve, reject) => {
        output.on('close', () => {
            console.log(`✅ 配置备份完成: ${backupName}.zip`);
            resolve(backupPath);
        });

        archive.on('error', (err) => {
            reject(err);
        });

        archive.pipe(output);

        // 添加环境配置文件
        if (fs.existsSync(config.envPath)) {
            archive.file(config.envPath, { name: '.env' });
        }

        // 添加配置目录
        if (fs.existsSync(config.configDir)) {
            archive.directory(config.configDir, 'config');
        }

        // 添加上传文件
        if (fs.existsSync(config.uploadsDir)) {
            archive.directory(config.uploadsDir, 'public/uploads');
        }

        archive.finalize();
    });
}

// 清理旧备份
function cleanupOldBackups() {
    const files = fs.readdirSync(config.backupDir);
    const backupFiles = files.filter(file => 
        file.startsWith('minecraft-panel-backup-') && 
        (file.endsWith('.sqlite') || file.endsWith('.zip'))
    );

    if (backupFiles.length > config.maxBackups) {
        // 按修改时间排序
        backupFiles.sort((a, b) => {
            const statA = fs.statSync(path.join(config.backupDir, a));
            const statB = fs.statSync(path.join(config.backupDir, b));
            return statA.mtime - statB.mtime;
        });

        // 删除最旧的备份
        const filesToDelete = backupFiles.slice(0, backupFiles.length - config.maxBackups);
        filesToDelete.forEach(file => {
            const filePath = path.join(config.backupDir, file);
            fs.unlinkSync(filePath);
            console.log(`🗑️  删除旧备份: ${file}`);
        });
    }
}

// 获取备份信息
function getBackupInfo() {
    const files = fs.readdirSync(config.backupDir);
    const backupFiles = files.filter(file => 
        file.startsWith('minecraft-panel-backup-') && 
        file.endsWith('.sqlite')
    );

    const backupInfo = backupFiles.map(file => {
        const filePath = path.join(config.backupDir, file);
        const stats = fs.statSync(filePath);
        return {
            name: file,
            size: stats.size,
            created: stats.birthtime,
            modified: stats.mtime
        };
    });

    return backupInfo.sort((a, b) => b.created - a.created);
}

// 显示备份信息
function showBackupInfo() {
    const backupInfo = getBackupInfo();
    
    console.log('📋 当前备份列表:');
    if (backupInfo.length === 0) {
        console.log('   无备份文件');
    } else {
        backupInfo.forEach((backup, index) => {
            const size = (backup.size / 1024 / 1024).toFixed(2);
            const created = moment(backup.created).format('YYYY-MM-DD HH:mm:ss');
            console.log(`   ${index + 1}. ${backup.name} (${size}MB) - ${created}`);
        });
    }
    console.log();
}

// 主备份函数
async function performBackup() {
    try {
        console.log('🚀 开始备份...');
        console.log();

        createBackupDirectory();
        
        const backupName = generateBackupName();
        
        // 备份数据库
        const dbBackup = backupDatabase(backupName);
        
        // 备份配置文件
        await backupConfig(backupName);
        
        // 清理旧备份
        cleanupOldBackups();
        
        // 显示备份信息
        showBackupInfo();
        
        console.log('==========================================');
        console.log('  ✅ 备份完成！');
        console.log('==========================================');
        console.log();
        console.log('📁 备份目录:', config.backupDir);
        console.log('📦 备份名称:', backupName);
        console.log('⏰ 备份时间:', moment().format('YYYY-MM-DD HH:mm:ss'));
        console.log();

    } catch (error) {
        console.error('❌ 备份失败:', error.message);
        process.exit(1);
    }
}

// 恢复备份
function restoreBackup(backupName) {
    console.log('🔄 开始恢复备份...');
    console.log();

    const dbBackupPath = path.join(config.backupDir, `${backupName}.sqlite`);
    const configBackupPath = path.join(config.backupDir, `${backupName}.zip`);

    if (!fs.existsSync(dbBackupPath)) {
        console.error('❌ 数据库备份文件不存在');
        process.exit(1);
    }

    try {
        // 恢复数据库
        console.log('📄 恢复数据库...');
        fs.copyFileSync(dbBackupPath, config.databasePath);
        console.log('✅ 数据库恢复完成');

        // 恢复配置文件
        if (fs.existsSync(configBackupPath)) {
            console.log('⚙️  恢复配置文件...');
            const unzipper = require('unzipper');
            
            fs.createReadStream(configBackupPath)
                .pipe(unzipper.Extract({ path: __dirname + '/..' }))
                .on('close', () => {
                    console.log('✅ 配置文件恢复完成');
                    console.log();
                    console.log('==========================================');
                    console.log('  ✅ 恢复完成！');
                    console.log('==========================================');
                    console.log();
                    console.log('📋 恢复的备份:', backupName);
                    console.log('⚠️  请重启面板以应用更改');
                    console.log();
                })
                .on('error', (error) => {
                    console.error('❌ 配置文件恢复失败:', error.message);
                });
        } else {
            console.log('⚠️  配置备份文件不存在，仅恢复数据库');
            console.log();
            console.log('==========================================');
            console.log('  ✅ 恢复完成！');
            console.log('==========================================');
            console.log();
            console.log('📋 恢复的备份:', backupName);
            console.log('⚠️  请重启面板以应用更改');
            console.log();
        }

    } catch (error) {
        console.error('❌ 恢复失败:', error.message);
        process.exit(1);
    }
}

// 命令行参数处理
function handleCommandLineArgs() {
    const args = process.argv.slice(2);
    
    if (args.length === 0) {
        // 默认执行备份
        performBackup();
    } else if (args[0] === 'list') {
        // 列出备份
        console.log('📋 备份列表:');
        showBackupInfo();
    } else if (args[0] === 'restore' && args[1]) {
        // 恢复备份
        restoreBackup(args[1]);
    } else if (args[0] === 'clean') {
        // 清理旧备份
        console.log('🗑️  清理旧备份...');
        cleanupOldBackups();
        showBackupInfo();
    } else {
        console.log('用法:');
        console.log('  node scripts/backup.js          - 执行备份');
        console.log('  node scripts/backup.js list     - 列出备份');
        console.log('  node scripts/backup.js restore <备份名> - 恢复备份');
        console.log('  node scripts/backup.js clean    - 清理旧备份');
        process.exit(1);
    }
}

// 运行脚本
handleCommandLineArgs();